//////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////// 
// Generate a mesh from 3D mesh

#include "boundaryFrom3DMesh.h"
#include "geom/point3d.h"

//////////////////////////////////////////////////////////////////////////
boundaryFrom3DMesh::boundaryFrom3DMesh(void)
{
  m_boundary = NULL;
}


//////////////////////////////////////////////////////////////////////////
boundaryFrom3DMesh::~boundaryFrom3DMesh(void)
{
}

//////////////////////////////////////////////////////////////////////////
 bool boundaryFrom3DMesh::process (tetraTopology *tetratopol)
{
  int i, j, id_node;

  // get max node id and reserve vector space to mapping
  int max_id = tetratopol->maxIdNode();
  m_mapNode.resize(max_id+1);
  for (i = 0; i < max_id+1; ++i)
    m_mapNode[i] = -1;

  // get nodes and boundary faces
  vector <node *> nodes = tetratopol->getNodes ();
  vector <triface *> bound = tetratopol->getBound ();

  // variables to insert to cTopology
  double *coords; 
  int    nnodes = 0, *conn;
  int    nfaces = (int) bound.size();
  conn = new int[nfaces*4];

  // build element connectivity
  for (i = 0; i < nfaces; ++i)
  {
    conn[i*4+0] = 3; // triangle element
    for (j = 0; j < 3; ++j)
    {
      id_node = bound[i]->vert[j];
      if (m_mapNode[id_node] == -1)
      {
        m_mapNode[id_node] = nnodes;
        ++nnodes;
      }
      conn[i*4+j+1] = m_mapNode[id_node];
    }
  }

  // inverse mapping node
  m_invMapNode.resize(nnodes);

  // nodes
  coords = new double[nnodes*3];
  for (i = 0; i < max_id+1; ++i)
  {
    if (m_mapNode[i] != -1)
    {
      for (j = 0; j < 3; ++j)
        coords[m_mapNode[i]*3+j] = nodes[i]->coord[j];

      m_invMapNode[m_mapNode[i]] = i;
    }
  }

  // create surface topology
  if (m_boundary != NULL)
    delete m_boundary;
  m_boundary = new cTopology;

  // InsertMesh
  m_boundary->InsertMesh(nnodes, nfaces, coords, conn, NULL);

  //   m_surfTopol->writeMatlab ("boundary.m", "wt");

  delete []conn;
  delete []coords;

  return true;
}

//////////////////////////////////////////////////////////////////////////
void boundaryFrom3DMesh::clear()
{
  m_invMapNode.clear();
  m_mapNode.clear();

  if (m_boundary != NULL)
    delete m_boundary;
}
